﻿#include <windows.h>
// windows 只是个C API
// 传指针 不传引用
// 没有成员函数

HWND ghMainWnd = NULL;

// instaceHandle 为程序句柄
// show 为展示方式，全屏
// 这个函数可以生成并展示一个窗口
// 成功返回true
// 失败返回false
bool InitWindowsApp(HINSTANCE instanceHandle, int show);

// 消息循环
int Run();

LRESULT CALLBACK
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);


// 整个程序的入口程序
// hInstance 程序句柄
// 不用管他
// 命令行参数
// 展示方式（全屏）
// 如果未进入消息循环返回0
// 如果进入消息循环返回WM_QUIT
int WINAPI
WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	PSTR pCmdLine,
	int nCmdShow)
{
	//如果未进入消息循环返回0
	if (!InitWindowsApp(hInstance, nCmdShow))
		return 0;

	// 如果进入消息循环返回WM_QUIT
	// 这里会发生类型转换 由WM_QUIT(UINT)转int
	return Run();
}

bool InitWindowsApp(HINSTANCE instanceHandle, int show)
{
	/*
	fill out the form (WNDCLASS) that express the details of the workspace of window
	regist the form (RegisterClass())
	create the window (CreateWindow())
	show the window (ShowWindow())
	keep updating the window (UpdateWindow())
	message loop
	END (msg.wParam)
	*/

	// 📜 fill out the form BEGIN

	WNDCLASS wc;

	// horizontal redraw and vertical reraw
	wc.style = CS_HREDRAW | CS_VREDRAW;

	wc.lpfnWndProc = WndProc;

	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;

	wc.hInstance = instanceHandle;

	wc.hIcon = NULL; // use default icon

	// ✅ https://blog.csdn.net/qq_22642239/article/details/99633129
	wc.hCursor = LoadCursor(0, IDC_NO);

	// background color of workspace
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

	wc.lpszMenuName = NULL;

	wc.lpszClassName = L"firstWnd";

	// 📜 fill out the form END

	//regist the form (RegisterClass()) and wc.lpszClassName will be registed
	if (!RegisterClass(&wc))
	{
		// the third param is title
		// if it is NULL, it will be "ERROR"
		MessageBox(NULL, L"RegisterClass Fail", L"TITLE ERROR", MB_OK);
		return false;
	}


	// 🖼create the window(CreateWindow()) BEGIN
	// to declear how the wnd will disappear
	ghMainWnd = CreateWindow(
		wc.lpszClassName,
		L"title",
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		0,
		0,
		instanceHandle,
		0);

	if (ghMainWnd == 0)
	{
		MessageBox(0, L"create Error", 0, 0);
		return false;
	}
	// 🖼create the window(CreateWindow()) END

	ShowWindow(ghMainWnd, show);

	UpdateWindow(ghMainWnd);

	return true;
}

// deliveryman : drop error msg
// dispatch msg to window procedure to process
int Run()
{
	// Event Loop
	MSG msg = { 0 };
	// MSG is a stuct type

	BOOL bRet = 0;
	// if error happen GetMessage return -1
	// if receve WM_QUIT , GetMessage return 0
	// GetMessage will jam the thread
	while ((bRet = GetMessage(&msg, 0, 0, 0)) != 0)
	{
		if (bRet == -1)
		{
			MessageBox(0, L"GET MESSage Failed", NULL, MB_OK);
			break;
		}
		else
		{
			// the members of mesg will be the param of window procedure
			// 
			// msg.message => msg
			// msg.wParam => wParam
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return (int)msg.wParam;
}

LRESULT CALLBACK
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_LBUTTONDOWN:
		MessageBox(0, L"Hello world", L"HEllO", MB_OK);
		return 0;
	case WM_KEYDOWN:
		if (wParam == VK_ESCAPE)
			DestroyWindow(ghMainWnd);
		return 0;
	case WM_DESTROY:
		//			exit code 
		PostQuitMessage(0);
		return 0;
	}

	return DefWindowProc(hWnd, msg, wParam, lParam);
}